package com.cynteka.cyfoman.core.collection;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.util.*;

/**
 * User: Sergey
 * Date: 30.07.11
 * Time: 7:44
 */
public class XMLAppender implements IRegistryAppender {
    private String xmlCollectionId = "xml";
    private String filesCollectionId = "files-xml";
    private String xmlLinkId = "xml";
    private String fileXmlLinkId = "file-xml";


    public class Collection extends BaseCollection<Node> {

        public Collection() {
            super(xmlCollectionId);
        }

        @Override
        public java.util.Collection<Node> getItems(Map<String, Object> params) {
            Object parent = null;
            List<Node> res = new ArrayList<Node>();
            if (params != null)
                parent = params.get(Constants.PARENT);

            if (parent instanceof File) {
                File file = (File) parent;
                try {

                    DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
                    f.setValidating(false);
                    DocumentBuilder builder = f.newDocumentBuilder();
                    Document doc = builder.parse(file);
                    NodeList nl = doc.getChildNodes();
                    populateChildren(nl, res);
                } catch (Exception e) {
                    // TODO fixit

                }
            } else if (parent instanceof Node) {
                Node node = (Node) parent;
                NodeList nl = node.getChildNodes();
                populateChildren(nl, res);
            }
            return res;
        }

    }

    protected void populateChildren(NodeList nl, java.util.Collection<Node> collection) {
        int l = nl.getLength();
        for (int i = 0; i < l; i++) {
            Node node = nl.item(i);
            collection.add(node);
        }
    }

    public class XMLLink extends BaseLink<Node, Node> {

        public XMLLink() {
            super(xmlLinkId, xmlCollectionId, xmlCollectionId, LinkType.ONE_TO_MANY);
        }

        @Override
        public java.util.Collection<Node> getDestinationItems(Node node) {
            java.util.Collection<Node> res = new ArrayList<Node>(node.getChildNodes().getLength());
            populateChildren(node.getChildNodes(), res);
            return res;
        }

        @Override
        public java.util.Collection<Node> getSourceItems(Node node) {
            return Arrays.asList(new Node[]{node.getParentNode()});
        }

    }

    public class FileXMLLink extends BaseLink<File, Node> {

        public FileXMLLink() {
            super(fileXmlLinkId, filesCollectionId, xmlCollectionId, LinkType.ONE_TO_MANY);
        }

        @Override
        public java.util.Collection<Node> getDestinationItems(File file) {
            Collection collection = (Collection) getOwner().getCollection(xmlCollectionId);

            Map<String, Object> params = new HashMap<String, Object>();
            params.put(Constants.PARENT, file);
            java.util.Collection<Node> res = collection.getItems(params);
            return res;
        }

        @Override
        public java.util.Collection<File> getSourceItems(Node node) {
            // TODO Investigate how to know parent file of a node,
            return Arrays.asList(new File[0]);
        }
    }


    @Override
    public ICollection[] getCollections() {
        return new ICollection[]{new Collection()};
    }

    @Override
    public ILink[] getLinks() {
        return new ILink[]{new XMLLink(), new FileXMLLink()};
    }

    public String getXmlCollectionId() {
        return xmlCollectionId;
    }

    public void setXmlCollectionId(String xmlCollectionId) {
        this.xmlCollectionId = xmlCollectionId;
    }

    public String getFilesCollectionId() {
        return filesCollectionId;
    }

    public void setFilesCollectionId(String filesCollectionId) {
        this.filesCollectionId = filesCollectionId;
    }

    public String getXmlLinkId() {
        return xmlLinkId;
    }

    public void setXmlLinkId(String xmlLinkId) {
        this.xmlLinkId = xmlLinkId;
    }

    public String getFileXmlLinkId() {
        return fileXmlLinkId;
    }

    public void setFileXmlLinkId(String fileXmlLinkId) {
        this.fileXmlLinkId = fileXmlLinkId;
    }
}
